# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2022/6/12 15:53
# @Author : xyjiang1216
# @Email : jiangxuyan@nudt.edu.cn
# @File : para_tbl_structure.py
# @Version: planner_builder 1.0

import ctypes

c_uint32 = ctypes.c_uint32


class ParaTbl_bits(ctypes.LittleEndianStructure):
    _fields_ = [
        # entry1
        ('rc_threshold', c_uint32, 9),
        ('tmp1', c_uint32, 23),
        # entry2
        ("hpriority_policing_threshold", c_uint32, 9),
        ('tmp2', c_uint32, 23),
        # entry3
        ("lpriority_policing_threshold", c_uint32, 9),
        ('tmp3', c_uint32, 23),
        # entry4
        ("qbv_or_qch", c_uint32, 1),
        ('tmp4', c_uint32, 31),
        # entry5
        ('committed_burst_size', c_uint32, 32),
        # entry6
        ('committed_information_rate', c_uint32, 32),
        # entry8
        ("schedule_period", c_uint32, 11),
        ('tmp8', c_uint32, 21),
        # entry9
        ("cycle_start_cyclen", c_uint32, 32),
        # entry10
        ("time_slot_length", c_uint32, 11),
        ('tmp10', c_uint32, 21),
    ]


class ParaTbl_bytes(ctypes.LittleEndianStructure):
    _fields_ = [
        ('entry1', c_uint32, 32),
        ('entry2', c_uint32, 32),
        ('entry3', c_uint32, 32),
        ('entry4', c_uint32, 32),
        ('entry5', c_uint32, 32),
        ('entry6', c_uint32, 32),
        ('entry8', c_uint32, 32),
        ('entry9', c_uint32, 32),
        ('entry10', c_uint32, 32),
    ]


class ParaTbl_union(ctypes.Union):
    _fields_ = [
        ("bit", ParaTbl_bits),
        ("byte", ParaTbl_bytes)
    ]


def _init_para_tbl(rc_threshold: None,
                   hpriority_policing_threshold: None,
                   lpriority_policing_threshold: None,
                   qbv_or_qch: None,
                   committed_burst_size: None,
                   committed_information_rate: None,
                   schedule_period: int,
                   cyclelen: int,
                   time_slot_length: int,
                   ):
    para_tbl = ParaTbl_union()
    para_tbl.bit.rc_threshold = rc_threshold
    para_tbl.bit.tmp1 = 0
    para_tbl.bit.hpriority_policing_threshold = hpriority_policing_threshold
    para_tbl.bit.tmp2 = 0
    para_tbl.bit.lpriority_policing_threshold = lpriority_policing_threshold
    para_tbl.bit.tmp3 = 0
    para_tbl.bit.qbv_or_qch = qbv_or_qch
    para_tbl.bit.tmp4 = 0
    para_tbl.bit.committed_burst_size = committed_burst_size
    para_tbl.bit.committed_information_rate = committed_information_rate
    para_tbl.bit.schedule_period = schedule_period
    para_tbl.bit.tmp8 = 0
    para_tbl.bit.cycle_start_cyclen = cyclelen
    para_tbl.bit.time_slot_length = time_slot_length
    para_tbl.bit.tmp10 = 0

    return para_tbl


class ParaTblEachNode:
    def __init__(self,
                 node_id: int,
                 schedule_period: int,
                 cyclelen: int,
                 time_slot_len: int,
                 node_type:str,
                 rc_threshold=64,
                 hpriority_policing_threshold=128,
                 lpriority_policing_threshold=256,
                 qbv_or_qch=0,
                 committed_burst_size=1,
                 committed_information_rate=1) -> None:
        self.node_id = node_id
        self.tbl_each_node = _init_para_tbl(rc_threshold,
                                            hpriority_policing_threshold,
                                            lpriority_policing_threshold,
                                            qbv_or_qch,
                                            committed_burst_size,
                                            committed_information_rate,
                                            schedule_period,
                                            cyclelen,
                                            time_slot_len)
        self.node_type = node_type


class ParaTbl:
    def __init__(self):
        self.tbl_set = []

    def append_tbl(self,
                   tbl: ParaTblEachNode) -> None:
        self.tbl_set.append(tbl)
